/*!
 * FlipCounter jQuery JavaScript Library v1.0
 * http://nickpettazzoni.com/flipcounter
 *
 * Copyright 2010, Nick Pettazzoni
 * Licensed under the Apache Version 2.0 License.
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Includes: jQuery JavaScript Library
 * http://jquery.com
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Date: Wed Oct 6 12:00:00 2010 -0500
 */

(function( $ ){
	//methods!
    var methods = {
		//constructor
        init:              function(options){
			settings = {
				myself : this,
				value : parseInt(this.html()),
				digits : 5,
				speed : 150,
				updating : false,
				pathToImages : '/images/numbers/'
			}
			if(options){
				$.extend(settings, options);
			}
			$(this).data('digits', []);
			$(this).data('settings', settings);
			
			//preload images
			var img;
			for(var i = 0; i <= 9; i++){
				img = new Image(100,100);
				img.src = settings.pathToImages + i + '_bottom.png';
				img = new Image(100,100);
				img.src = settings.pathToImages + i + '_top.png';
			}
			img = new Image(100,100);
			img.src = settings.pathToImages + '-_bottom.png';
			img = new Image(100,100);
			img.src = settings.pathToImages + '-_top.png';
			
			this.each(function(){
			    $(this).flipCounter('blankScreen');
			    $(this).flipCounter('updateValue'); 
			});
        },
        getValue:          function(){
    		return $(this).data('settings').value;
        },
        getDigitsArray:    function(){
            return $(this).data('digits');
        },
        getDigitEl:        function(n){
            return $(this).data('settings').myself.flipCounter('getDigitsArray')[n];
        },
        getDigitValue:     function(n){
            return $(this).data('settings').myself.flipCounter('getDigitEl', n).data('number');
        },
        getDigitTopEl:     function(n){
            return $(this).data('digits')[n].children("img.flipCounter_digit_top").not("img.flipCounter_newguy");
        },
        getDigitBottomEl:  function(n){
            return $(this).data('digits')[n].children("img.flipCounter_digit_bottom").not("img.flipCounter_newguy");
        },
        blankScreen:       function(){
            var digitals = '';
			for(var i = 1; i <= $(this).data('settings').digits; i++){
                digitals += '<div class="flipCounter_digit"></div>';
            }
			$(this).data('settings').myself.html(digitals);
			var my = $(this);
			$(this).data('settings').myself.children().css({
	            'position':'relative',
	            'width':'35px',
	            'height':'55px',
	            'float':'left'
	        }).each(function(index, Element){
				$(this).html('<img class="flipCounter_digit_top" src="' + my.data('settings').pathToImages + '0_top.png"/> <img class="flipCounter_digit_bottom" src="' + my.data('settings').pathToImages + '0_bottom.png"/>');
				$(this).children(".flipCounter_digit_top").css({
                	'position':'absolute',
                	'bottom':'28px',
                	'left':'0px',
                	'width':'35px',
                	'height':'26px'
                });
				$(this).children(".flipCounter_digit_bottom").css({
                	'position':'absolute',
                	'top':'29px',
                	'left':'0px',
                	'width':'35px',
                	'height':'26px'
                });
				my.data('digits')[index + 1] = $(this);
				my.data('digits')[index + 1].data('number', 0);
			});
        },
        updateDigitTo:     function(d,n,c){
            var me = $(this).data('settings').myself;
			var myDigit = me.flipCounter('getDigitEl', d);

			myDigit.data('number', n);
            
            /* //this is for the animation borkend fixery
			$(this).data('settings').myself.flipCounter('getDigitTopEl', d).attr("src", $(this).data('settings').pathToImages + n + '_top.png');
            $(this).data('settings').myself.flipCounter('getDigitBottomEl', d).attr("src", $(this).data('settings').pathToImages + n + '_bottom.png');
			*/
            $('<img class="flipCounter_digit_top flipCounter_newguy" />').insertBefore(me.flipCounter('getDigitTopEl', d)).attr("src", me.data('settings').pathToImages + n + '_top.png').css({
                	'position':'absolute',
                	'bottom':'28px',
                	'left':'0px',
                	'width':'35px',
                	'height':'26px'
                });
			
			me.flipCounter('getDigitTopEl', d).animate({ height: '0px'}, me.data('settings').speed, "linear", function(){
				$(this).siblings("img.flipCounter_newguy").removeClass("flipCounter_newguy");
				$(this).remove();
				$('<img class="flipCounter_digit_bottom flipCounter_newguy"/>').insertAfter(me.flipCounter('getDigitBottomEl', d)).attr("src", me.data('settings').pathToImages + n + '_bottom.png').css({
                	'position':'absolute',
                	'top':'29px',
                	'left':'0px',
                	'width':'35px',
                	'height':'0px'
                }).animate({ height: "26px"}, me.data('settings').speed, "linear", function(){  
					me.flipCounter('getDigitBottomEl', d).remove();
					$(this).removeClass("flipCounter_newguy");
					
					c();
				});
			});
        },
        updateValue:       function(){
			var me = $(this);
			var thisSettings = $(this).data('settings');
			thisSettings.updating = true;
            var valstr = '' + thisSettings.value;
    
    		for(var x = valstr.length; x < $(this).data('digits').length - 1; x++){
    			valstr = '0' + valstr;
    		}
			//choose which digits to update, based on whether or not they changed value
			var updatesPending = new Array();
			var counter = 0;
    	    for(var i = 0; i < valstr.length; i++){
    			if($(this).data('settings').myself.flipCounter('getDigitEl', $(this).data('settings').digits - i).data('number') != valstr[(valstr.length - 1 - i)]){
					updatesPending[counter] = {'digit' : $(this).data('settings').digits - i, 'value': valstr.charAt(valstr.length - 1 - i)};
					counter++;
    			}
    	    }
			if(updatesPending.length == 0){
				thisSettings.updating = false;
				me.dequeue('qvalueUpdates');
			}else{
				for(y in updatesPending){
					//console.log('running pending updates:');
					//console.log(updatesPending);
					var callback;
					//console.log('pending update #' + y);
					if(y == updatesPending.length - 1){
						//console.log('is the last digit update for #' + me.attr('id'));
						callback = function(){
							thisSettings.updating = false;
							//console.log('dequeueing an update on: #' + me.attr('id'));
							me.dequeue('qvalueUpdates');
						};
					}else{
						//console.log((updatesPending.length - y) + ' updates remaining for #' + me.attr('id')); 
						callback = function(){
							$.noop();
						};
					}
					$(this).flipCounter('updateDigitTo', updatesPending[y].digit, updatesPending[y].value, callback);
				}
			}
        },
        updateValueBy:       function(n){
			if(!$(this).data('settings').updating){
				$(this).data('settings').value = $(this).data('settings').value + n;
				$(this).flipCounter('updateValue');
			}else{
				console.log('enqueueing an update on: #' + $(this).attr('id'));
				var me = $(this);
				me.queue('qvalueUpdates', function(){
					console.log('executing queued updateValueBy on: #' + $(this).attr('id'));
					me.data('settings').value = me.data('settings').value + n;
					me.flipCounter('updateValue');
				});
			}
        },
        updateValueTo:       function(n){
			if(!$(this).data('settings').updating){
				$(this).data('settings').value = n;
				$(this).flipCounter('updateValue');
			}else{
				console.log('enqueueing an update on: #' + $(this).attr('id'));
				var me = $(this);
				me.queue('qvalueUpdates', function(){
					console.log('executing queued updateValueTo on: #' + $(this).attr('id'));
					me.data('settings').value = n;
					me.flipCounter('updateValue');
				});
			}
        }
    }

	//actually add the plugin to the jquery object
    $.fn.flipCounter = function( method ) {
  
        // Method calling logic
        if ( methods[method] ) {
          return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
          return methods.init.apply( this, arguments );
        } else {
          $.error( 'Method ' +  method + ' does not exist on jQuery.flipCounter' );
        } 
    
    };
})( jQuery );